package com.powernode.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.constant.MessageConstants;
import com.powernode.domain.SysUser;
import com.powernode.domain.SysUserRole;
import com.powernode.dto.PasswordDto;
import com.powernode.exception.handler.BusinessException;
import com.powernode.mapper.SysUserMapper;
import com.powernode.mapper.SysUserRoleMapper;
import com.powernode.service.SysUserRoleService;
import com.powernode.service.SysUserService;
import com.powernode.util.AuthUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService{

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    //@Autowired
    //private BCryptPasswordEncoder bCryptPasswordEncoder;
    //
    //@Bean
    //public BCryptPasswordEncoder bCryptPasswordEncoder(){
    //    return new BCryptPasswordEncoder();
    //}

    /**
     * 修改密码
     *
     * @param passwordDto
     */
    @Override
    public Boolean updatePassword(PasswordDto passwordDto) {
        // 首先判断新密码是否不为空
        String newPassword = passwordDto.getNewPassword().trim();

        if (!StringUtils.hasText(newPassword)){
            throw new RuntimeException("新密码不能为空");
        }

        // 判断旧密码是否和数据库中一致
        // 根据用户id查询用户信息
        Long loginUserId = AuthUtil.getLoginUserId();

        SysUser sysUser = sysUserMapper.selectById(loginUserId);

        String dbOldPassword = sysUser.getPassword();

        boolean matches = bCryptPasswordEncoder.matches(passwordDto.getPassword(), dbOldPassword);

        if (!matches){
            throw new BusinessException(MessageConstants.PASSWORD_MATCHES_ERROR_MESSAGE);
        }

        //修改密码
        // 加密
        String encode = bCryptPasswordEncoder.encode(newPassword);
        // 更新数据
        boolean update = this.lambdaUpdate().eq(SysUser::getUserId, loginUserId).set(SysUser::getPassword, encode).update();


        return update;
    }

    /**
     * 新增管理员
     * 新增管理员和角色
     *  这里就是一个面试题,@Transactional注解在什么时候下会失效
     *  如果不指定rollbackFor=Exception.class 当抛出IO异常的时候 ,就会失效
     * @param sysUser
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer saveUser(SysUser sysUser) {

        // 1. 判断用户名是否不为空
        String username = sysUser.getUsername();
        if (!StringUtils.hasText(username)){
            throw new BusinessException(MessageConstants.USER_NOT_NULL_MESSAGE);
        }

        // 判断用户是否已被占用
        SysUser dbUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));

        if (dbUser != null){
            throw new BusinessException(MessageConstants.USER_EXISTS_MESSAGE);
        }


        // 2. 保存用户信息
        // 设置创建人id
        sysUser.setCreateUserId(AuthUtil.getLoginUserId());
        // 设置创建时间
        sysUser.setCreateTime(new Date());
        sysUser.setShopId(1L);

        // 对密码加密
        String encodedPassword = bCryptPasswordEncoder.encode(sysUser.getPassword());

        sysUser.setPassword(encodedPassword);

        // 插入数据后,需要返回主键值,用来添加到sys_user_role表中
        int insert = sysUserMapper.insert(sysUser);

        if (insert > 0 ){

            Long sysUserId = sysUser.getUserId();

            // 3. 保存用户角色信息
            if (sysUser.getRoleIdList()!= null && sysUser.getRoleIdList().size() > 0){
                //
                List<SysUserRole> sysUserRoles = new ArrayList<>();
                for (Long roleId : sysUser.getRoleIdList()){
                    SysUserRole sysUserRole = new SysUserRole();
                    /*
                        这里的userId是空的

                        把userId的属性设置成auto 就好了
                     */
                    sysUserRole.setUserId(sysUserId);
                    sysUserRole.setRoleId(roleId);
                    // 不建议在循环里面操作数据库
                    // sysUserRoleService.save(sysUserRole);
                    sysUserRoles.add(sysUserRole);
                }
                // 批量插入
                sysUserRoleService.saveBatch(sysUserRoles);
            }
        }


        return insert;
    }


    /**
     * 通过id查询用户
     * @param userId
     * @return
     */
    @Override
    public SysUser querySysUserById(Integer userId) {
        SysUser sysUser = sysUserMapper.selectById(userId);

        // 隐藏密码
        sysUser.setPassword(MessageConstants.PASSWORD_HIDDEN);

        List<SysUserRole> list = sysUserRoleService.list(
                new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId)
        );
        if (list != null && list.size() > 0){
            sysUser.setRoleIdList(list.stream().map(SysUserRole::getRoleId).collect(Collectors.toList()));
        }

        return sysUser;
    }

    /**
     * 修改用户信息
     * 防止声明式事务失效,在Transactional上添加rollbackFor=Exception.class
     * 不然如果报IO异常就会导致回滚失效.
     * @param sysUser
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateSysUser(SysUser sysUser) {

        String password = sysUser.getPassword();
        if (StringUtils.hasText(password)){
            // 有密码,则对密码加密
            String encodePassword = bCryptPasswordEncoder.encode(sysUser.getPassword());
            sysUser.setPassword(encodePassword);
        }


        int i = sysUserMapper.updateById(sysUser);

        // 删除用户角色,然后重新添加用户角色
        sysUserRoleService.remove(
                new LambdaQueryWrapper<SysUserRole>()
                        .eq(SysUserRole::getUserId, sysUser.getUserId())
        );
        // 添加用户角色映射关系
        List<Long> roleIdList = sysUser.getRoleIdList();

        if (roleIdList != null && roleIdList.size() > 0){
            List<SysUserRole> sysUserRoles = new ArrayList<>();

            for (Long roleId : roleIdList) {
                SysUserRole sysUserRole = new SysUserRole();
                sysUserRole.setRoleId(roleId);
                sysUserRole.setUserId(sysUser.getUserId());
                sysUserRoles.add(sysUserRole);
            }
            sysUserRoleService.saveBatch(sysUserRoles);
        }

        return i;
    }

    /**
     * 批量或单个删除用户信息
     * @param ids
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer removeBatchOrOne(List<Long> ids) {
        // 根据用户id删除用户信息
        int i = sysUserMapper.deleteBatchIds(ids);

        // 根据用户id删除用户角色信息
        sysUserRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>()
                .in(SysUserRole::getUserId, ids)
        );

        return i;
    }
}
